
from Engine import *

#import SafeEval


bindKeyDown(pygame.K_a, self.player.giveCommand, Player.CMD_LEFT, True)

# TODO: Think about state management

Game.commands = {"player_left_start": curry(self.player.giveCommand, Player.CMD_LEFT, True), \
				 "player_left_stop": curry(self.player.giveCommand, Player.CMD_LEFT, False), \
				 "player_fire_start": curry(self.player.giveCommand, Player.CMD_FIRE, True)
				 # ...
				 }

Game.states = {}
Game.states["splash_screen"] = GameState()
Game.states["play"] = GameState()

# The first game state added is the initial game state used by the engine
engine.addGameState("splash_screen")
engine.addGameState("play")
engine.addGameState("menu")
# create splash models
# create timer
# when timer ticks, hide current splash model and show next one
# when reached end of splash model list, change state to menu
engine.changeGameStateTo("menu", keep_current_in_memory=False)
# create background model
# create menu gui
# respond to gui events
# when "Play" clicked, change state to play
engine.changeGameStateTo("play", keep_current_in_memory=True, keep_current_running=False)
# check for resumed pause
	# resume
# else
	# load level
# run game
# if pause, change state to menu
engine.changeGameStateTo("menu", keep_current_in_memory=True)
# when game ends, change state to menu
engine.changeGameStateTo("menu", keep_current_in_memory=False)

bindKeyUp(pygame.K_a, self.player.giveCommand, Player.CMD_LEFT, False)
bindMouseButtonDown(0, self.player.giveCommand, Player.CMD_FIRE, True)
bindMouseButtonUp(0, self.player.giveCommand, Player.CMD_FIRE, False)

def bindKeyDown(key, response, *args, **kwargs):
	response = curry(response, *args, **kwargs)
	self.key_bindings[key]


#TODO: put this stuff into engine or something
def curry(func,*args,**kwargs):
    def curried(*moreargs,**morekwargs):
        morekwargs.update(kwargs)
        return func(*(moreargs+args),**morekwargs)
    return curried

class Player(object):
    def __init__(self,name):
        self.name = name
        self.entity = None

the_player = Player('someone')

gamerules = RuleSet()
gamerules.bindings = {}
    
@gamerules.eventMaker
def commandGiver(start,command):
    the_player.entity.giveCommand(command, start)

@gamerules.rule('inputevent')
def handleInput(event):
    try:        
        if event.type == pygame.KEYDOWN:
            gamerules.bindings[event.key](True)
        elif event.type == pygame.KEYUP:
            gamerules.bindings[event.key](False)
    except KeyError:
        print 'nokey'

@gamerules.rule('inputevent')
def handleMouse(event):
    try:        
        if event.type == pygame.MOUSEBUTTONDOWN:
            gamerules.bindings[300+event.button](True,event.pos) #TODO: fix mouse button binding
        elif event.type == pygame.MOUSEBUTTONUP:
            gamerules.bindings[300+event.button](False,event.pos)
        elif event.type == pygame.MOUSEMOTION:
            gamerules.bindings[304](event.pos)
    except KeyError:
        print 'nokey'
            
class Game(object):
    def __init__(self):
        # Create game engine instance
        self.engine = Engine()
        
        # Engine settings
        self.engine.tickRate = 60
        self.engine.gravity = -5.0
        self.engine.worldMinX = -20.0
        self.engine.worldMinY = -20.0
        self.engine.worldMaxX = 20.0
        self.engine.worldMaxY = 20.0
        # TODO: Work out why turning this on makes the physics go haywire
        self.engine.usePhysicsSleeping = False
        self.engine.windowWidth = 800
        self.engine.windowHeight = 600
        self.engine.forceResolution = True
        self.engine.fullscreen = False
        #self.engine.physicsIterations = 10
        self.engine.velocity_iterations = 10
        self.engine.position_iterations = 8
        self.engine.init()

        # Note: The GUI system is in need of a major look-at
        self.mygui = MyGUI(engine=self.engine, parent=self.engine.gui.root)

        self.engine.renderer.enableParallax(True, False)

        # Set up the render layers
        self.engine.renderer.addLayer("background", 0)
        self.engine.renderer.addLayer("distant", 0.5)
        self.engine.renderer.addLayer("behind", 1)
        self.engine.renderer.addLayer("play", 1)
        self.engine.renderer.addLayer("infront", 1)
        self.engine.renderer.addLayer("foreground", 2.0)
        self.engine.renderer.addLayer("GUI", 0)

        # Set up the camera
        self.engine.renderer.camera.setMaxZoomRate(0.01)
        self.engine.renderer.camera.setZoomAccel(0.01)
        self.engine.renderer.camera.zoomTo(0.2)

        # TODO: Remove this and replace with the level's solid_geometry
        groundShapeDef = b2PolygonDef()
        groundShapeDef.SetAsBox(40.0, 0.1, b2Vec2(0.0, -3.0), 0.0)
        self.engine.physics_world.GetGroundBody().CreateShape(groundShapeDef)

        world = self.engine.world
        
        self.playerChar = world.createEntity(PlayerChar, \
                                             "PlayerChar", \
                                             b2Vec2(1.2, 0.2), \
                                             0.0)

        the_player.entity = self.playerChar
        
        self.applyKeyBindings()
        
        self.engine.renderer.camera.followBody(self.playerChar.referenceBody)
        
        #self.engine.entities.append( CameraController(self) )
        world.createEntity(CharacterBody, \
                           "NPC1", \
                           b2Vec2(-0.5, 0.1), \
                           0.0)
        for i in range(20):
            world.createEntity(Body, \
                               None, \
                               b2Vec2(-0.5, 0.2+0.1*i))

        # TODO: Work out what this crap I wrote is
        """
        bodyDef = b2BodyDef()
        bodyDef.position = b2Vec2(3.0, 3.0)
        bodyDef.fixedRotation = False
        self.rot_test_body = self.engine.world.CreateBody(bodyDef)
        polyDef = b2PolygonDef()
        polyDef.SetAsBox(0.5, 0.5)
        polyDef.density = 1.0
        self.rot_test_body.CreateShape(polyDef)
        self.rot_test_body.SetMassFromShapes()
        jointDef = b2RevoluteJointDef()
        jointDef.Initialize(self.engine.world.GetGroundBody(), self.rot_test_body, b2Vec2(2.5, 2.5))
        jointDef.lowerAngle = 0.0
        jointDef.upperAngle = b2_pi/180.0 * 90
        jointDef.enableLimit = True
        jointDef.enableMotor = True
        self.rot_test_joint = self.engine.world.CreateJoint(jointDef)
        
        jointDef = b2RevoluteJointDef()
        jointDef.body1 = self.engine.entities["CyclicWorldBody1"].body
        jointDef.body2 = self.engine.entities["CyclicWorldBody1"].body
        #jointDef.referenceAngle = 0.0
        jointDef.collideConnected = False
        jointDef.localAnchor1 = b2Vec2(-0.1, 0.1)
        jointDef.localAnchor2 = b2Vec2(-0.1, -0.1)
        
        #jointDef.anchorPoint = b2Vec2(-0.1, 0.1) #self.entities[1].body.GetWorldCenter()
        joint = self.engine.world.CreateJoint(jointDef)
        """
        
        level = world.createEntity(Level, \
                                   "level")
        level.load("Level1")

        self.engine.run()
        
    def applyKeyBindings(self):
        # TODO: Implement these functions
        """
        self.engine.bindKeyPressToEvent('w', self.playerChar.onCommand, PlayerChar.CMD_UP, 'start')
        self.engine.bindKeyReleaseToEvent('w', self.playerChar.onCommand, PlayerChar.CMD_UP, 'stop')
        self.engine.bindKeyPressToEvent('a', self.playerChar.onCommand, PlayerChar.CMD_LEFT, 'start')
        self.engine.bindKeyReleaseToEvent('a', self.playerChar.onCommand, PlayerChar.CMD_LEFT, 'stop')
        self.engine.bindKeyPressToEvent('s', self.playerChar.onCommand, PlayerChar.CMD_DOWN, 'start')
        self.engine.bindKeyReleaseToEvent('s', self.playerChar.onCommand, PlayerChar.CMD_DOWN, 'stop')
        self.engine.bindKeyPressToEvent('d', self.playerChar.onCommand, PlayerChar.CMD_RIGHT, 'start')
        self.engine.bindKeyReleaseToEvent('d', self.playerChar.onCommand, PlayerChar.CMD_RIGHT, 'stop')
        self.engine.bindKeyPressToEvent('rbuttondown', self.playerChar.onCommand, PlayerChar.CMD_JETPACK, True)
        self.engine.bindKeyReleaseToEvent('rbuttonup', self.playerChar.onCommand, PlayerChar.CMD_JETPACK, False)
        self.engine.bindKeyPressToEvent('z', self.playerChar.onCommand, PlayerChar.CMD_PRONE)
        self.engine.bindKeyPressToEvent('lshift', self.playerChar.onCommand, PlayerChar.CMD_RUN, True)
        self.engine.bindKeyReleaseToEvent('lshift', self.playerChar.onCommand, PlayerChar.CMD_RUN, False)
        """
    
class PlayerChar(CharacterBody):
    # Commands
    # Note: These have a 1 to 1 relationship with bound input keys\buttons.
    # Note: The actual action that occurs when these commands are issued is
    #        context-sensitive.
    DIR_UP = CMD_UP = 0
    DIR_DOWN = CMD_DOWN = 1
    DIR_LEFT = CMD_LEFT = 2
    DIR_RIGHT = CMD_RIGHT = 3
    CMD_RUN = 4
    CMD_JETPACK = 5
    CMD_FIRE = 6
    CMD_GRENADE = 7
    CMD_NEXT_WEAPON = 8
    CMD_PREV_WEAPON = 9
    COMMAND_COUNT = 10
    # ...
    
    #Control parameters
    WALK_FORCE = 5.0
    CROUCHWALK_FORCE = 3.0
    RUN_FORCE = 8.0
    MAX_WALK_SPEED = 2.5
    MAX_CROUCHWALK_SPEED = 1.0
    MAX_RUN_SPEED = 4.0
    BRAKE_FORCE = 2.0
    #MAX_JUMP_SPEED = 0.8
    MAX_JUMP_TIME = 0.2
    MAX_JUMP_FORCE = 100.0
    JETPACK_FORCE = 7.0
    #JUMP_DELAY = 0.5
    
    # Quick up\down\left\right direction vectors matching the command 
    directions = {DIR_UP: b2Vec2(0.0, 1.0), \
                  DIR_DOWN: b2Vec2(0.0, -1.0), \
                  DIR_LEFT: b2Vec2(-1.0, 0.0), \
                  DIR_RIGHT: b2Vec2(1.0, 0.0)}
    
    def __init__(self, engine, name, refPos, refAngle):
        CharacterBody.__init__(self, engine, name, refPos, refAngle)

        # TODO: Decide if this is the way to go
        engine.addEventListener('input', self.handleOSEvent)
        
        #self.isJetpacking = False
        #self.isJumping = False
        #self.isRunning = False
        #self.isMovingLeft = False
        #self.isMovingRight = False
        #self.isMovingUp = False
        #self.maxPropulsionSpeed = 0.0
        #self.maxPropulsionSpeed2 = 0.0
        #self.jumpForce = 0.0
        
        self.hasCommand = [False for i in range(PlayerChar.COMMAND_COUNT)]
        self.hadCommand = [False for i in range(PlayerChar.COMMAND_COUNT)]
        self.direction = b2Vec2_zero
        self.jumpStartTime = -1.0
        self.isOnGround = False
        
        # This is all hack, used to quickly test out some faux-IK
        """
        self.killJoint("LeftShoulder")
        self.killJoint("LeftElbow")
        self.killJoint("LeftWrist")
        hookDef = b2BodyDef()
        hookDef.position.Set(3.0, 1.0)
        self.hookBody = self.engine.world.CreateBody(hookDef)
        self.hookJoint = None
        """
        
    def handleOSEvent(self, engine, event):
        # TODO: Replace these with proper event bindings
        '''if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
            self.giveCommand(PlayerChar.CMD_UP, True)
        elif event.type == pygame.KEYUP and event.key == pygame.K_w:
            self.giveCommand(PlayerChar.CMD_UP, False)
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_a:
            self.giveCommand(PlayerChar.CMD_LEFT, True)
        elif event.type == pygame.KEYUP and event.key == pygame.K_a:
            self.giveCommand(PlayerChar.CMD_LEFT, False)
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
            self.giveCommand(PlayerChar.CMD_DOWN, True)
        elif event.type == pygame.KEYUP and event.key == pygame.K_s:
            self.giveCommand(PlayerChar.CMD_DOWN, False)
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_d:
            self.giveCommand(PlayerChar.CMD_RIGHT, True)
        elif event.type == pygame.KEYUP and event.key == pygame.K_d:
            self.giveCommand(PlayerChar.CMD_RIGHT, False)
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_LSHIFT:
            self.giveCommand(PlayerChar.CMD_RUN, True)
        elif event.type == pygame.KEYUP and event.key == pygame.K_LSHIFT:
            self.giveCommand(PlayerChar.CMD_RUN, False)
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
            self.giveCommand(PlayerChar.CMD_JETPACK, True)
        elif event.type == pygame.MOUSEBUTTONUP and event.button == 3:
            self.giveCommand(PlayerChar.CMD_JETPACK, False)'''
        gamerules.raiseEvent("inputevent",event=event)

    ##@NetworkedEvent
    #@netevent
    def giveCommand(self, command, value):
        """Contains state context logic for response to input commands.

            Control keys must be bound to this method and no other PlayerChar
             methods to ensure the event is sent to the server and to prevent
             1337 h4x0ring.
        """
        
        # TODO: See if can avoid the need for this when implementing jumping and crouching
        self.hadCommand[command] = self.hasCommand[command]
        self.hasCommand[command] = value
        
        if self.isOnGround:
            if value == True:
                if command == PlayerChar.CMD_LEFT:
                    self.direction.x = -1.0
                elif command == PlayerChar.CMD_RIGHT:
                    self.direction.x = 1.0
            else:
                pass
        else: # if in the air
            # Check for any new motion commands and re-set the direction vector
            if value == True:
                if command == PlayerChar.CMD_LEFT:
                    self.direction.x = -1.0
                elif command == PlayerChar.CMD_RIGHT:
                    self.direction.x = 1.0
                elif command == PlayerChar.CMD_UP:
                    self.direction.y = 1.0
                elif command == PlayerChar.CMD_DOWN:
                    self.direction.y = -1.0
            else:
                if not self.hasCommand[PlayerChar.CMD_LEFT] and not self.hasCommand[PlayerChar.CMD_RIGHT]:
                    self.direction.x = 0.0
                if not self.hasCommand[PlayerChar.CMD_UP] and not self.hasCommand[PlayerChar.CMD_DOWN]:
                    self.direction.y = 0.0
            
        #if command == PlayerChar.CMD_JUMP:
        #    # Check for new jump command
        #    if self.hasCommand[CMD_JUMP] and not self.hadCommand[CMD_JUMP]:
        #        self.jumpStartTime = self.engine.timeMgr.getTime()
            
        
        """
        self.isMoving = CMD_LEFT or CMD_RIGHT
        self.direction = 
        
        if command == PlayerChar.CMD_LEFT:
            
        elif command == PlayerChar.CMD_RIGHT:
            
           command is PlayerChar.CMD_RIGHT:
            self.direction = PlayerChar.directions[command]
            self.isMoving = value
            
            # TODO: Put state changing code in here instead of these function calls
            if not self.isJetpacking:
                self.__walk(command, value)
            else:
                self.fly(command, value)
        elif command is PlayerChar.CMD_UP:
            if not self.isJetpacking:
                self.__jump(value)
            else:
                self.fly(command, value)
        elif command is PlayerChar.CMD_DOWN:
            if not self.isJetpacking:
                self.crouch(value)
            else:
                self.fly(command, value)
        elif command is PlayerChar.CMD_JETPACK:
            self.__jetpack(value)
        elif command is PlayerChar.CMD_RUN:
            self.isRunning = value
        elif command is PlayerChar.CMD_FIRE:
            self.fire()
        elif command is PlayerChar.CMD_NEXT_WEAPON:
            self.changeWeapon(PlayerChar.NEXT_WEAPON)
        """
    """
    def __walk(self, direction, start_or_stop):
        if start_or_stop == 'start':
            self.propulsionDampingFactor = 0.0
            if not self.isRunning:
                # Either (currently better):
                self.propulsionForce = PlayerChar.directions[direction] * PlayerChar.WALK_FORCE
                self.setMaxPropulsionSpeed(PlayerChar.MAX_WALK_SPEED)
                # or:
                #self.movementState = PlayerChar.WALKING

                #self.animation.set("walking")
            else:
                self.propulsionForce = PlayerChar.directions[direction] * PlayerChar.RUN_FORCE
                self.setMaxPropulsionSpeed(PlayerChar.MAX_RUN_SPEED)

                self.animation.set("running")
        elif start_or_stop == 'stop':
            # TODO: Work out how to apply 'braking' to bring PlayerChar to zero speed.
            #       Need flag to let know that need to apply force proportional to velocity (i.e., damped)?
            # TODO: Try out the damping factor method and see how it goes
            self.propulsionDampingFactor = PlayerChar.BRAKE_FORCE
            self.propulsionForce = b2Vec2_zero
            #self.setMaxPropulsionSpeed(0.0)
        else:
            raise Exception("PlayerChar.__walk( ) received unknown string value for start_or_stop of '" + start_or_stop + "'")
        
    def __jetpack(self, direction, value):
        if value == True:
            self.isJetpacking = True
            self.animation.set("jetpacking")
        else:
            # Just turn off the jetpack
            self.isJetpacking = False
            self.propulsionDampingFactor = 0.0
            self.propulsionForce = b2Vec2_zero
            self.setMaxPropulsionSpeed(0.0)

    def __fly(self, direction, value):
        if start_or_stop == 'start':
            self.propulsionDampingFactor = 0.0
            # TODO: Consider direction dependent forces and animations
            self.propulsionForce = PlayerChar.directions[direction] * PlayerChar.JETPACK_FORCE
            self.setMaxPropulsionSpeed(PlayerChar.MAX_JETPACK_SPEED)
            self.animation.set("jetpacking")
        elif start_or_stop == 'stop':
            # Just turn off the jetpack
            self.propulsionDampingFactor = 0.0
            self.propulsionForce = b2Vec2_zero
            self.setMaxPropulsionSpeed(0.0)
        else:
            raise Exception("PlayerChar.__jetpack( ) received unknown string value for start_or_stop of '" + start_or_stop + "'")

    def __jump(self, start_or_stop):
        if start_or_stop == 'start':
            self.propulsionDampingFactor = 0.0
            self.jumpStartTime = self.engine.timeMgr.getTime()
            self.isJumping = True
            # No jumping force is applied til PlayerChar.JUMP_DELAY has elapsed.
            self.propulsionForce = b2Vec2_zero
            self.setMaxPropulsionSpeed(0.0)
            # Awesome way would be to slowly crouch down as jump key is held and
            #  release when the key is released, causing the PlayerChar to
            #  spring up, similar to Diver. But may be too hard to make stable.
            #self.animation.set("jumping")
        elif start_or_stop == 'stop':
            if self.isJumping:
                self.isJumping = False
                self.propulsionForce = b2Vec2(0.0, self.jumpForce)
                self.jumpForce = 0.0
                #self.setMaxPropulsionSpeed(0.0)
                
                jumpTime = self.engine.timeMgr.getTime() - self.jumpStartTime
                jumpPowerFraction = jumpTime / PlayerChar.MAX_JUMP_TIME
                if jumpPowerFraction > 1.0:
                    jumpPowerFraction = 1.0
                self.referenceBody.ApplyForce(b2Vec2(0.0, jumpPowerFraction * PlayerChar.MAX_JUMP_FORCE),
                                              self.referenceBody.GetWorldCenter())
        else:
            raise Exception("PlayerChar.__jump( ) received unknown string value for start_or_stop of '" + start_or_stop + "'")
    
    def setMaxPropulsionSpeed(self, speed):
        self.maxPropulsionSpeed = speed
        self.maxPropulsionSpeed2 = speed*speed
    """
    def update(self, timeStep):
        
        """
        if self.isJumping:
            jumpTime = self.engine.timeMgr.getTime() - self.jumpStartTime
            if jumpTime >= PlayerChar.MAX_JUMP_TIME:
                self.__jump('stop')
        """
        """
                self.isJumping = False
                self.propulsionForce = b2Vec2_zero
                self.setMaxPropulsionSpeed(0.0)
            elif jumpTime < PlayerChar.JUMP_DELAY:
                self.jumpForce += PlayerChar.JUMP_FORCE
            elif jumpTime >= PlayerChar.JUMP_DELAY:
                self.propulsionForce = b2Vec2(0.0, self.jumpForce)
                self.jumpForce = 0.0
        """
        self.isOnGround = True#(self.bodies["LeftFoot"].GetWorldCenter().y <= -1.0 + 0.3)
        
        if self.isOnGround:
            # TODO: Consider finding velocity dot surface vector instead of this
            vel = self.referenceBody.GetLinearVelocity().x
            speed = abs(vel)
            # Check for ground movement commands
            if self.hasCommand[PlayerChar.CMD_LEFT] or self.hasCommand[PlayerChar.CMD_RIGHT]:
                # Check for desired direction changes
                if self.direction * vel < 0.0:
                    # Apply damping to simulate braking with feet
                    self.referenceBody.ApplyForce(PlayerChar.BRAKE_FORCE * b2Vec2(-1.0*speed*vel, 0.0), \
                                                  self.referenceBody.GetWorldCenter())
                else: # movement is already in the desired direction
                    if self.hasCommand[PlayerChar.CMD_RUN]:
                        if speed < PlayerChar.MAX_RUN_SPEED:
                            self.referenceBody.ApplyForce(PlayerChar.RUN_FORCE * self.direction, \
                                                  self.referenceBody.GetWorldCenter())
                    elif self.hasCommand[PlayerChar.CMD_DOWN]:
                        if speed < PlayerChar.MAX_CROUCHWALK_SPEED:
                            self.referenceBody.ApplyForce(PlayerChar.CROUCHWALK_FORCE * self.direction, \
                                                  self.referenceBody.GetWorldCenter())
                    else:
                        if speed < PlayerChar.MAX_WALK_SPEED:
                            self.referenceBody.ApplyForce(PlayerChar.WALK_FORCE * self.direction, \
                                                  self.referenceBody.GetWorldCenter())
            else: # if not moving horizontally
                # Apply damping to simulate braking with feet
                self.referenceBody.ApplyForce(PlayerChar.BRAKE_FORCE * b2Vec2(-1.0*speed*vel, 0.0), \
                                              self.referenceBody.GetWorldCenter())
                
            
            """jumpTime = self.engine.timeMgr.getTime() - self.jumpStartTime
            # Check for new jump command
            if self.hasCommand[PlayerChar.CMD_UP] and not self.hadCommand[PlayerChar.CMD_UP]:
                self.jumpStartTime = self.engine.timeMgr.getTime()
            # Check for end of jump command
            elif jumpTime >= PlayerChar.MAX_JUMP_TIME or \
               not self.hasCommand[PlayerChar.CMD_UP] and self.hadCommand[PlayerChar.CMD_UP]:
                jumpPowerFraction = jumpTime / PlayerChar.MAX_JUMP_TIME
                if jumpPowerFraction > 1.0:
                    jumpPowerFraction = 1.0
                self.referenceBody.ApplyForce(b2Vec2(0.0, jumpPowerFraction * PlayerChar.MAX_JUMP_FORCE),
                                              self.referenceBody.GetWorldCenter())
            """
            # Check for new crouch command
            if self.hasCommand[PlayerChar.CMD_DOWN] and not self.hadCommand[PlayerChar.CMD_DOWN]:
                # TODO: Apply crouch
                pass
            # Check for end of crouch command
            elif not self.hasCommand[PlayerChar.CMD_DOWN] and self.hadCommand[PlayerChar.CMD_DOWN]:
                # TODO: Un-apply crouch
                pass
        else: # if in the air
            """
            # Check for any new motion commands and re-set the direction vector
            if self.hasCommand[PlayerChar.CMD_LEFT] and not self.hadCommand[PlayerChar.CMD_LEFT]:
                self.direction.x = -1.0
            elif self.hasCommand[PlayerChar.CMD_RIGHT] and not self.hadCommand[PlayerChar.CMD_RIGHT]:
                self.direction.x = 1.0
            elif not self.hasCommand[PlayerChar.CMD_RIGHT] and not self.hasCommand[PlayerChar.CMD_LEFT]:
                self.direction.x = 0.0
            if self.hasCommand[PlayerChar.CMD_UP] and not self.hadCommand[PlayerChar.CMD_UP]:
                self.direction.y = 1.0
            elif self.hasCommand[PlayerChar.CMD_DOWN] and not self.hadCommand[PlayerChar.CMD_DOWN]:
                self.direction.y = -1.0
            elif not self.hasCommand[PlayerChar.CMD_UP] and not self.hasCommand[PlayerChar.CMD_DOWN]:
                self.direction.y = 0.0
            """
            if self.hasCommand[PlayerChar.CMD_JETPACK]:
                # Apply jetpack force
                # TODO: Apply force at jetpack exhaust point
                self.bodies["UpperTorso"].ApplyForce(PlayerChar.JETPACK_FORCE * self.direction, \
                                              self.bodies["UpperTorso"].GetWorldCenter())
            else: # if just free-falling
                pass
        """
        # Apply self-propulsion to the body
        vel = self.referenceBody.GetLinearVelocity()
        speed2 = vel.LengthSquared()
        speed = math.sqrt(speed2)
        if speed2 < self.maxPropulsionSpeed2:
            self.referenceBody.ApplyForce(self.propulsionForce - self.propulsionDampingFactor*vel*speed,
                                          self.referenceBody.GetWorldCenter())
        """

        # Faux-IK test hack
        """
        dist = self.hookBody.GetWorldCenter() - self.bodies["LeftHand"].GetWorldCenter()
        dist2 = dist.LengthSquared()
        if dist2 <= 0.05**2:
            if not self.hookJoint:
                jointDef = b2RevoluteJointDef()
                jointDef.Initialize(self.bodies["LeftHand"], self.hookBody, self.hookBody.GetWorldCenter())
                self.hookJoint = self.engine.world.CreateJoint(jointDef)
        elif dist2 <= 1.5**2:
            self.bodies["LeftHand"].ApplyForce(dist/math.sqrt(dist2)*0.3, self.bodies["LeftHand"].GetWorldCenter())
        """
        
        CharacterBody.update(self, timeStep)
        
class MyGUI(GUI.Frame):
    def __init__(self, engine, parent):
        GUI.Frame.__init__(self, parent, "MyGUI")
        cmdStart = GUI.Button(engine, self, "cmdStart", (-0.9, -0.05))
        GUI.Button(engine, self, "cmdExit", (-0.8, -0.1))
        GUI.CheckBox(engine, self, "chkOudenIsCool", (-0.9, -0.2))
        cmdStart.bringToFront()
        
        #self.addChild( GUI.Label("lblTitle", "Ouden") )
        
    def cmdStart_Click(self, *args, **kwargs):
        #self.controls["cmdStart"].visible = false
        print "cmdStart_Click", kwargs
        
    def cmdExit_Click(self, *args, **kwargs):
        print "cmd_Exit_Click. Powering down engine."
        kwargs["engine"].running = False
        
    def cmdExit_MouseMove(self, *args, **kwargs):
        print "cmdExit_MouseMove ", kwargs["pos"]


def printer(tf,message):
    if tf: print message

def mbdown(tf,pos):
    print pos

def mmove(pos):
    print 'moving: ',pos

gamerules.bindings[pygame.K_d] = curry(commandGiver,PlayerChar.CMD_RIGHT)
gamerules.bindings[pygame.K_a] = curry(commandGiver,PlayerChar.CMD_LEFT)
gamerules.bindings[pygame.K_w] = curry(commandGiver,PlayerChar.CMD_UP)
gamerules.bindings[pygame.K_s] = curry(commandGiver,PlayerChar.CMD_DOWN)
#gamerules.bindings[303] = curry(commandGiver,PlayerChar.CMD_UP)
#gamerules.bindings[303] = curry(commandGiver,PlayerChar.CMD_DOWN)
gamerules.bindings[303] = mbdown
gamerules.bindings[304] = mmove
#gamerules.bindings[pygame.K_ESC] =
#setTrace()
game = Game()

